home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / DocShell / RlShSync.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  11.0 KB  |  408 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        RlShSync.cpp
  3.  
  4.     Contains:    Document-synchronization stuff in the shell
  5.  
  6.     Owned by:    Nick Pilch
  7.     
  8.                 Portions by Mark Linton (see issue 23 of 'develop')
  9.  
  10.     Copyright:    © 1995 - 1996 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.  
  14.          <5>     12/3/96    JP        1401371,1162540: Call SetProcessName &
  15.                                     SetProcessIcon
  16.          <4>     10/5/96    JP        1162540,1162541: Process name call
  17.          <3>     9/17/96    RA        1363261: Moved FindFinder to
  18.                                     ODProcessUtils.cpp and renamed it
  19.                                     FindProcess
  20.          <2>     5/22/96    EL        #1304982: if file name is changed and there
  21.                                     is no other change, save the document so
  22.                                     that the property is updated immediately.
  23.          <6>     9/29/95    eeh        1287262: use ShellDef.h
  24.          <5>     9/12/95    JP        Check for null draft (build break)
  25.          <4>     9/11/95    JP        1269048 & 1283405: Cope with multiple
  26.                                     documents
  27.          <3>      9/5/95    TÇ        FBs: 1266428, 1274419, 1274421, 1274423,
  28.                                     1274429, 1274435 Fixed the Shell to handle
  29.                                     multiple documents in a process. Needed for
  30.                                     CyberDog.
  31.          <2>     8/15/95    TÇ        1261899 DocUtils getters should be renamed
  32.                                     Acquire___
  33.          <1>      8/8/95    jpa        first checked in
  34. */
  35.  
  36.  
  37. #ifndef _RLSHELL_
  38. #include "RlShell.h"
  39. #endif
  40.  
  41. #ifndef _SHELLDEF_
  42. #include "ShellDef.h"
  43. #endif
  44.  
  45. #ifndef SOM_ODDispatcher_xh
  46. #include <Disptch.xh>
  47. #endif
  48.  
  49. #ifndef SOM_ODWindowState_xh
  50. #include <WinStat.xh>
  51. #endif
  52.  
  53. #ifndef _DLOGUTIL_
  54. #include <DlogUtil.h>
  55. #endif
  56.  
  57. #ifndef _DOCUTILS_
  58. #include <DocUtils.h>
  59. #endif
  60.  
  61. #ifndef _INFOUTIL_
  62. #include <InfoUtil.h>
  63. #endif
  64.  
  65. #ifndef _PASCLSTR_
  66. #include <PasclStr.h>
  67. #endif
  68.  
  69. #ifndef _TEMPOBJ_
  70. #include <TempObj.h>
  71. #endif
  72.  
  73. #ifndef _ODPROCESSUTILS_
  74. #include "ODProcessUtils.h"
  75. #endif
  76.  
  77. #ifndef _PROCESSHACK_
  78. #include "ProcessHack.h"
  79. #endif
  80.  
  81. #include <AppleEvents.h>
  82. #include <AERegistry.h>
  83. #include <Aliases.h>
  84. #include <Drag.h>
  85. #include <Folders.h>
  86. #include <Script.h>
  87.  
  88.  
  89. #undef ASK_SAVE_TO_TRASH    /* Define to ask user what to do when modified
  90.                                document is dragged to trash */
  91.  
  92.  
  93. //==============================================================================
  94. // Constants
  95. //==============================================================================
  96.  
  97. enum {                            // Buttons for kSHLDragToTrashAlert
  98.     kTrashSaveIndex = 1,
  99.     kTrashDontSaveIndex,
  100.     kTrashRetrieveIndex
  101. };
  102.  
  103. #ifndef kAEFinderSuite
  104. #define kAEFinderSuite 'fndr'
  105. #endif
  106.  
  107. #ifndef kAEPutAway
  108. #define kAEPutAway 'ptwy'
  109. #endif
  110.  
  111. const ODSShort kNumBetween = 20;
  112.  
  113.  
  114. //==============================================================================
  115. // Static Function Prototypes
  116. //==============================================================================
  117.  
  118. static void  ZoomWindowToTrash( WindowPtr );
  119. static OSErr SendFinderEvent(AEEventClass, AEEventID, const FSSpec& );
  120. static ODULong GetMostRecentVolModDate();
  121.  
  122.  
  123. //==============================================================================
  124. // Static Globals
  125. //==============================================================================
  126. static ODULong    lastChecked = 0;    // time of the last disk check
  127.  
  128. //==============================================================================
  129. // Shell Methods
  130. //==============================================================================
  131.  
  132. //-------------------------------------------------------------------------------------
  133. // RealShell::CheckFileLocation
  134. //-------------------------------------------------------------------------------------
  135.  
  136. ODBoolean
  137. RealShell::CheckFileLocation( )
  138. {
  139.     ODULong                n = 1;
  140.     ODULong                nowTime;
  141.     char                firstCStr[256], secondCStr[256];
  142.  
  143.     nowTime = GetMostRecentVolModDate();
  144.     if (nowTime == lastChecked)
  145.         return kODFalse;    // bail if we've already checked during this second
  146.     
  147.     ODDocument* document = ODGetNthOpenDocument(fEV, fSession, n);
  148.     RETURN_IF_NULL(document, kODFalse);
  149.  
  150.     while (document != kODNULL)
  151.     {
  152.         TempPlatformFile file = GetPlatformFileFromContainer(fEV, 
  153.                 document->GetContainer(fEV));
  154.         ODDraft* tempDraft = ODGetTempDraftFromOpenDocument(fEV, fSession, document);
  155.         if (tempDraft != kODNULL)
  156.         {
  157.             TempODPart root = ODAcquireRootPartOfDraft(fEV, tempDraft);
  158.             TempODName partName = ODGetPOName(fEV, root, kODNULL);
  159.             TempODName fileName = file->GetName();
  160.             
  161.             if(strcmp( GetITextString(partName, firstCStr),
  162.                     GetITextString(fileName, secondCStr) ) != 0)
  163.             {
  164.                 // Filename changed: save doc if no other change else rename root part
  165.                 if (!fAPPLProcess)
  166.                     SetProcessName(fileName);
  167.                 if (!ODDocumentHasChanges(fEV, fSession, document))
  168.                     ODSaveDocument(fEV, fSession, document);
  169.                 else {
  170.                     ODSetPOName(fEV, root, fileName);
  171.                     ODRenamePartWindows(fEV, fSession, root, partName, fileName);
  172.                 }
  173.             }
  174.         }
  175.         
  176.         if(file->IsInTrash() ) {
  177.             // File has been moved to trash: close document.
  178. #ifdef ASK_SAVE_TO_TRASH
  179.             if( this->HasWriteAccess() && tempDraft && tempDraft->ChangedFromPrev(fEV) )
  180.                 this->Notify(&RealShell::NotifyDragToTrash);
  181.             else
  182. #endif
  183.                 this->CloseTrashedDocument(document, kAEYes);
  184.             return fDispatcher->ShouldExit(fEV);
  185.         } else
  186.             // If it's no longer in the trash, don't bother to notify:
  187.             this->CancelNotification(&RealShell::NotifyDragToTrash);
  188.         document = ODGetNthOpenDocument(fEV, fSession, ++n);
  189.     }
  190.     lastChecked = nowTime;
  191.     return kODFalse;
  192. }
  193.  
  194.  
  195. //-------------------------------------------------------------------------------------
  196. // RealShell::NotifyDragToTrash
  197. //-------------------------------------------------------------------------------------
  198.  
  199. void
  200. RealShell::NotifyDragToTrash( ODULong /*refCon*/ )
  201. {
  202. #ifdef ASK_SAVE_TO_TRASH
  203.     char    fileName[256];
  204.     this->GetUserFileName(fileName, 255);
  205.     CToPascalString(fileName);
  206.     ParamText((ConstStr255Param)fileName, kODNULL,kODNULL,kODNULL);
  207.  
  208.     ODSShort result= ShowAlert(fEV,kSHLDragToTrashAlert,GetODDialogFilter(),fSession);
  209.     if( result == kTrashRetrieveIndex )
  210.         SendFinderEvent(kAEFinderSuite,kAEPutAway, fFile.GetFileSpec());
  211.     else
  212.         this->CloseTrashedDocument( result==kTrashSaveIndex ?kAEYes :kAENo);
  213. #endif
  214. }
  215.  
  216.  
  217. void
  218. RealShell::CloseTrashedDocument(ODDocument* document, DescType saveOptions )
  219. {
  220.     ODSaveDocument(fEV, fSession, document);
  221.     {
  222.         TempODWindow w = fWindowState->AcquireFrontRootWindow(fEV);
  223.         ZoomWindowToTrash(w->GetPlatformWindow(fEV));
  224.     }
  225.     if (ODCloseDocument(fEV, fSession, document))
  226.         fDispatcher->Exit(fEV);
  227. }
  228.  
  229.  
  230. //==============================================================================
  231. // Static Functions
  232. //==============================================================================
  233.  
  234.  
  235. //-------------------------------------------------------------------------------------
  236. // GetTrashIconRect
  237. //-------------------------------------------------------------------------------------
  238.  
  239. static OSErr
  240. GetTrashIconRect(Rect *aRect) {
  241.     OSErr theError;
  242.     short theVRefNum;
  243.     long theDirID;
  244.     Str255 theName;
  245.     CInfoPBRec pb;
  246.     Point thePoint;
  247.     
  248.     theError = FindFolder(kOnSystemDisk, kTrashFolderType, kDontCreateFolder,
  249.         &theVRefNum, &theDirID);
  250.     if (theError == fnfErr) {
  251.         theError = FindFolder(kOnSystemDisk, kWhereToEmptyTrashFolderType, kDontCreateFolder,
  252.             &theVRefNum, &theDirID);
  253.     }
  254.     if (theError == noErr) {
  255.         pb.dirInfo.ioNamePtr = theName;
  256.         pb.dirInfo.ioVRefNum = theVRefNum;
  257.         pb.dirInfo.ioDrDirID = theDirID;
  258.         pb.dirInfo.ioFDirIndex = -1;    /* use ioDrDirID */
  259.         theError = PBGetCatInfoSync(&pb);
  260.         if (theError == noErr) {
  261.             thePoint.v = pb.dirInfo.ioDrUsrWds.frLocation.v;
  262.             thePoint.h = pb.dirInfo.ioDrUsrWds.frLocation.h;
  263.             LocalToGlobal(&thePoint);
  264.             aRect->top = thePoint.v;
  265.             aRect->left = thePoint.h;
  266.             aRect->bottom = aRect->top + 32;
  267.             aRect->right = aRect->left + 32;
  268.         }
  269.     }
  270.     return theError;
  271. }
  272.  
  273.  
  274. //-------------------------------------------------------------------------------------
  275. // UpdateDesktop
  276. //-------------------------------------------------------------------------------------
  277.  
  278. static void
  279. UpdateDesktop( )
  280. {
  281.     EventRecord theEvent;
  282.     (void)WaitNextEvent(0, &theEvent, 10, kODNULL);
  283. }
  284.  
  285. //-------------------------------------------------------------------------------------
  286. // ZoomWindowToTrash
  287. //-------------------------------------------------------------------------------------
  288.  
  289. static void
  290. ZoomWindowToTrash( WindowPtr aWindow )
  291. {
  292.     GrafPtr curPort, wmgrPort;
  293.     GetPort(&curPort);
  294.  
  295.     Rect theStartingRect, theEndingRect;
  296.     theStartingRect = aWindow->portRect;
  297.     SetPort(aWindow);
  298.     LocalToGlobal((Point*)&theStartingRect.top);
  299.     LocalToGlobal((Point*)&theStartingRect.bottom);
  300.  
  301.     HideWindow(aWindow);
  302.     UpdateDesktop();
  303.     GetWMgrPort(&wmgrPort);
  304.     SetPort(wmgrPort);
  305.  
  306.     OSErr theError = GetTrashIconRect(&theEndingRect);
  307.     if( !theError )
  308.         ZoomRects(&theStartingRect,&theEndingRect,kNumBetween,zoomNoAcceleration);
  309.  
  310.     SetPort(curPort);
  311. }
  312.  
  313.  
  314. #ifdef ASK_SAVE_TO_TRASH
  315.  
  316. //-------------------------------------------------------------------------------------
  317. // SendFinderEvent
  318. //-------------------------------------------------------------------------------------
  319. #define kSystemType    'FNDR'
  320. #define kFinderSig    'MACS'
  321.  
  322. static OSErr
  323. SendFinderEvent(AEEventClass aClass, AEEventID anID, 
  324.                 const FSSpec &aFile)
  325. {
  326.     OSErr theError;
  327.     AppleEvent theAppleEvent, theReplyEvent;
  328.     AEDesc targetAddrDesc, theFileDesc;
  329.     AEDescList theFileDescList;
  330.     AliasHandle theFileAlias;
  331.     ProcessSerialNumber theFinder;
  332.     
  333.     theAppleEvent.dataHandle = nil;
  334.     theFileDescList.dataHandle = nil;
  335.     theFileDesc.dataHandle = nil;
  336.     theFileAlias = nil;
  337.     theError = FindProcess(&theFinder,kFinderSig,kSystemType);
  338.     if (theError == noErr) {    
  339.         theError = AECreateDesc(typeProcessSerialNumber, 
  340.             (Ptr)&theFinder, sizeof(ProcessSerialNumber), 
  341.             &targetAddrDesc);
  342.     }
  343.     if (theError == noErr) {    
  344.         theError = AECreateList(nil, 0, false, &theFileDescList);
  345.     }
  346.     if (theError == noErr) {
  347.         theError = NewAlias(nil, &aFile, &theFileAlias);
  348.     }
  349.     if (theError == noErr) {
  350.         HLock((Handle) theFileAlias);
  351.         theError = AECreateDesc(typeAlias, (Ptr) *theFileAlias, 
  352.             GetHandleSize((Handle) theFileAlias), &theFileDesc);
  353.         HUnlock((Handle) theFileAlias);
  354.     }
  355.     if (theError == noErr) {
  356.         theError = AEPutDesc(&theFileDescList, 0, &theFileDesc);
  357.     }
  358.     if (theError == noErr) {
  359.         theError = AECreateAppleEvent(aClass, anID, 
  360.             &targetAddrDesc, kAutoGenerateReturnID, 
  361.             kAnyTransactionID, &theAppleEvent);
  362.     }
  363.     if (theError == noErr) {
  364.         theError = AEPutParamDesc(&theAppleEvent, keyDirectObject, 
  365.             &theFileDescList);
  366.     }
  367.     if (theError == noErr) {
  368.         theError = AESend(&theAppleEvent, &theReplyEvent, 
  369.             kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, 
  370.             kAENormalPriority, kAEDefaultTimeout, nil, nil);
  371.     }
  372.     if (theAppleEvent.dataHandle != nil) {
  373.         (void)AEDisposeDesc(&theAppleEvent);
  374.     }
  375.     if (theFileDescList.dataHandle != nil) {
  376.         (void)AEDisposeDesc(&theFileDescList);
  377.     }
  378.     if (theFileDesc.dataHandle != nil) {
  379.         (void)AEDisposeDesc(&theFileDesc);
  380.     }
  381.     if (theFileAlias != nil) {
  382.         DisposeHandle((Handle)theFileAlias);
  383.     }
  384.     return theError;
  385. }
  386.  
  387. #endif /*ASK_SAVE_TO_TRASH*/
  388.  
  389. ODULong
  390. GetMostRecentVolModDate()
  391. {
  392.     ODULong            bigModDate = 0;
  393.     OSErr            err = noErr;
  394.     ODSShort        index = 0;
  395.     HParamBlockRec    pb;
  396.     
  397.     pb.volumeParam.ioNamePtr = kODNULL; /* Don't care about name */
  398.     pb.volumeParam.ioVRefNum = 0;    /* Don't care about vRefNum */
  399.     while (err == noErr)
  400.     {
  401.         pb.volumeParam.ioVolIndex = ++index;
  402.         err = PBHGetVInfoSync(&pb);
  403.         if (err == noErr && pb.volumeParam.ioVLsMod > bigModDate)
  404.             bigModDate = pb.volumeParam.ioVLsMod;
  405.     }
  406.     return bigModDate;
  407. }
  408.